package com.google.code.training_java_basic.oop;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;

public class FTPServiceImpl implements FTPService {

	private FTPClient client;
	private String localWorkingDirectory;
	private String remoteWorkingDirectory;
	
	private static final Logger logger = Logger.getLogger(FTPServiceImpl.class);

	public FTPServiceImpl() {

		client = new FTPClient();
	}


	public String getRemoteWorkingDirectory() {
		return remoteWorkingDirectory;
	}


	public void setRemoteWorkingDirectory(String remoteWorkingDirectory) {
		this.remoteWorkingDirectory = remoteWorkingDirectory;
	}


	public String getLocalWorkingDirectory() {
		return localWorkingDirectory;
	}

	public void setLocalWorkingDirectory(String localWorkingDirectory) {
		this.localWorkingDirectory = localWorkingDirectory;
	}

	
	public boolean downloadRemoteFiles(NetworkElementConnector connector, String regex ) {

		boolean result = false;
		boolean loginStatus = false;
		File file;
		String tmplocalWorkingDirectory;
		List<String> filesToDownload = new ArrayList<String>();
		tmplocalWorkingDirectory = this.getLocalWorkingDirectory();
		
		if(isAvailable(connector)){
			try {
						
				client.connect(connector.getNetworkElement().getIp());
				loginStatus = client.login(connector.getAccount().getUserName(),connector.getAccount().getPassword());
				
				if (loginStatus) {
				logger.debug(LoggerFormatter.format(1,LoggerFormatter.Level.DEBUG,	"Successfully connected with username: "
								+ connector.getAccount().getUserName() + " to "
								+ connector.getNetworkElement().getIp()));
				}

				client.setFileType(FTP.ASCII_FILE_TYPE);
				client.changeWorkingDirectory(this.getRemoteWorkingDirectory());
				this.setLocalWorkingDirectory(tmplocalWorkingDirectory  +  "\\"+ connector.getNetworkElement().getNetworkElementName());
				file = new File(this.getLocalWorkingDirectory());
				file.mkdirs();
				filesToDownload = getListofFilesToDownload(client, regex);
				retrieveFiles(client, filesToDownload);
				this.setLocalWorkingDirectory(tmplocalWorkingDirectory);
				client.logout();

			} catch (IOException e) {
				logger.error(LoggerFormatter.format(1,LoggerFormatter.Level.ERROR,e.getStackTrace().toString()));
			}
		}
		return result;
	}

	
	private  List<String> getListofFilesToDownload(FTPClient client, String regex) throws IOException {
		
		FTPFile[] listOfRemoteFiles;
		List<String> result = new ArrayList<String>();

		if( (listOfRemoteFiles = client.listFiles()) != null)  {
			for (FTPFile file: listOfRemoteFiles) {
				if((file.getType() == 0) && (file.getName().matches(regex)) ) {
					result.add(file.getName());
				}
			}
		}
		return result;
	}

	private boolean retrieveFiles(FTPClient client, List<String> filesToDownload) {
	
		FileOutputStream fileOutputStream;
		boolean result = false;	
		boolean resultPerFile = false;	
		int fileOkCounter = 0;
	
		for (String fileName: filesToDownload) {
			try {
				fileOutputStream = new FileOutputStream(this.getLocalWorkingDirectory() + "\\"+ fileName);
				
				if(resultPerFile = client.retrieveFile(fileName, fileOutputStream)) {
					fileOkCounter++; 
					if(!resultPerFile) {
						logger.debug(LoggerFormatter.format(1,LoggerFormatter.Level.DEBUG,	"Failed to download file: "
							+ fileName));
					}
				 }
			} catch (IOException e) {
				logger.error(LoggerFormatter.format(1,LoggerFormatter.Level.ERROR,e.getStackTrace().toString()));
			}
		}
		
		if(fileOkCounter == filesToDownload.size()) { result = true; }
		return result;
	}
	
		
    public boolean isAvailable(NetworkElementConnector connector) {
        boolean result = false;
        try {
			client.connect(connector.getNetworkElement().getIp());
			result = client.login(connector.getAccount().getUserName(),connector.getAccount().getPassword());
		} catch (SocketException e1) {
			logger.error(LoggerFormatter.format(1,LoggerFormatter.Level.ERROR,e1.getStackTrace().toString()));
		} catch (IOException e1) {
			logger.error(LoggerFormatter.format(1,LoggerFormatter.Level.ERROR,e1.getStackTrace().toString()));
		} finally {
			try {
				client.logout();
			} catch (IOException e) {
				logger.error(LoggerFormatter.format(1,LoggerFormatter.Level.ERROR,e.getStackTrace().toString()));
			}
		}

		return result;
	}


}
